package bigbrother.log.daylog;

import bigbrother.ParameterChecker;
import org.joda.time.DateMidnight;

import java.io.File;
import java.io.Serializable;

/**
 * Used to uniquely identify a {@link DayLog}, so that it can be loaded or saved from the file system, and stored and
 * accessed from the cache.
 *
 * @author Hans Haggstrom
 */
public final class DayLogId
        implements Serializable
{

    //======================================================================
    // Private Fields

    private final String myChannelName;
    private final DateMidnight myDate;

    //======================================================================
    // Private Constants

    private static final String FILENAME_PART_SEPARATOR = "-";
    private static final String FILENAME_EXTENSION = ".xml";
    private static final String DIRECTORY_SEPARATOR = "/";//File.separator;

    //======================================================================
    // Public Methods

    //----------------------------------------------------------------------
    // Constructors

    /**
     * Creates a new ID for identifying a specific {@link DayLog}.
     *
     * @param channelName the name for the channel.
     * @param date        the date the {@link DayLog} is from.
     */
    public DayLogId( final String channelName,
                     final DateMidnight date )
    {
        ParameterChecker.checkNotNull( channelName, "channelName" );
        ParameterChecker.checkNotNull( date, "date" );

        myDate = date;
        myChannelName = channelName;
    }

    //----------------------------------------------------------------------
    // Other Public Methods

    /**
     * @return the date the {@link DayLog} is from (the time is the start of that thay, 00:00).
     */
    public DateMidnight getDate()
    {
        return myDate;
    }


    /**
     * @return the name of the channel the {@link DayLog} is from.
     */
    public String getChannelName()
    {
        return myChannelName;
    }


    /**
     * @param logStorageDirectory the directory under which the logs are stored.
     *
     * @return the log file corresponding to this {@link DayLogId}, given the base directory where the logs are stored.
     */
    public File getLogFileLocation( final File logStorageDirectory )
    {
        return new File( logStorageDirectory, getChannelNameForFileSystem() + DIRECTORY_SEPARATOR +
                                              getDate().getYear() + DIRECTORY_SEPARATOR +
                                              getDate().getMonthOfYear() + DIRECTORY_SEPARATOR +
                                              getLogFileName() );
    }


    /**
     * @return the name of the log file corresponding to this {@link DayLogId}.
     */
    public String getLogFileName()
    {
        return getChannelNameForFileSystem() + FILENAME_PART_SEPARATOR +
               getDate().getYear() + FILENAME_PART_SEPARATOR +
               getDate().getMonthOfYear() + FILENAME_PART_SEPARATOR +
               getDate().getDayOfMonth() + FILENAME_EXTENSION;
    }

    //----------------------------------------------------------------------
    // Caononical Methods

    public String toString()
    {
        return "DayLogId{" +
               "myChannelName='" + myChannelName + '\'' +
               ", myDate=" + myDate +
               '}';
    }


    public boolean equals( final Object o )
    {
        if ( this == o )
        {
            return true;
        }
        if ( o == null || getClass() != o.getClass() )
        {
            return false;
        }

        final DayLogId dayLogId = (DayLogId) o;

        if ( myChannelName != null ? !myChannelName.equals( dayLogId.myChannelName ) : dayLogId.myChannelName != null )
        {
            return false;
        }
        if ( myDate != null ? !myDate.equals( dayLogId.myDate ) : dayLogId.myDate != null )
        {
            return false;
        }

        return true;
    }


    public int hashCode()
    {
        int result;
        result = ( myChannelName != null ? myChannelName.hashCode() : 0 );
        result = 31 * result + ( myDate != null ? myDate.hashCode() : 0 );
        return result;
    }

    //======================================================================
    // Private Methods

    private String getChannelNameForFileSystem()
    {
        // TODO: Remove special characters from channel names, such as !, #, mIRC color codes, etc, that are not supported by file systems.
        // Replace them with some unique transcoding?  Escape sequence + unicode character code?
        return getChannelName();
    }

}
